package zip

import (
    "archive/zip"
    "fmt"
    "io"
    "os"
    "path"
    "regexp"
    "strings"
)

var DO_LOG = true

func CompressDir(source string, target string, noZips []string) error {
    f1, err := os.Open(source)
    if err != nil {
        return err
    }
    defer f1.Close()
    d, err := os.Create(target)
    if err != nil {
        return err
    }
    defer d.Close()
    w := zip.NewWriter(d)
    defer w.Close()
    noZipRegs := make([]regexp.Regexp, 0)
    for _, nz := range noZips {
        fmt.Println(nz)
        var wildcardSeat = strings.Index(nz, "*")
        if wildcardSeat == 0 {

        } else if wildcardSeat == len(nz)-1 {

        }
        nz = strings.ReplaceAll(nz, ".", "\\.")
        nz = strings.ReplaceAll(nz, "*", ".*")
        nzr := regexp.MustCompile(nz)
        noZipRegs = append(noZipRegs, *nzr)
        fmt.Println(nz)
        fmt.Println("================================")
    }
    noZipRegs = append(noZipRegs, *regexp.MustCompile("^[\\\\.git]"))
    return compress(f1, "", w, noZipRegs)
}

func compress(file *os.File, prefix string, zipWriter *zip.Writer, noZips []regexp.Regexp) error {
    info, err := file.Stat()
    defer file.Close()
    if err != nil {
        return err
    }
    if info.IsDir() {
        prefix = path.Join(prefix, info.Name())
        dirPath := prefix + "/"
        if inNoZips(dirPath, noZips) {
            return nil
        }
        if DO_LOG {
            fmt.Printf("Create dir : %s\n", dirPath)
        }
        fileInfos, err := file.Readdir(-1)
        if err != nil {
            return err
        }
        if len(fileInfos) > 0 {
            for _, fi := range fileInfos {
                f, err := os.Open(path.Join(file.Name(), fi.Name()))
                if err != nil {
                    return err
                }
                err = compress(f, prefix, zipWriter, noZips)
                if err != nil {
                    return err
                }
            }
        } else {
            header, err := zip.FileInfoHeader(info)
            if err != nil {
                return err
            }
            header.Name = dirPath
            _, err = zipWriter.CreateHeader(header)
            if err != nil {
                return err
            }
        }
    } else {
        header, err := zip.FileInfoHeader(info)
        if err != nil {
            return err
        }
        filePath := path.Join(prefix, header.Name)
        if inNoZips(filePath, noZips) {
            return nil
        }
        if DO_LOG {
            fmt.Printf("Adding file : %s\n", filePath)
        }
        header.Name = filePath
        header.Method = zip.Deflate
        writer, err := zipWriter.CreateHeader(header)
        if err != nil {
            return err
        }
        _, err = io.Copy(writer, file)
        if err != nil {
            return err
        }
    }
    return nil
}

func inNoZips(file string, noZips []regexp.Regexp) bool {
    for _, reg := range noZips {
        if reg.MatchString(file) {
            return true
        }
    }
    return false
}
